/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package net.scalan;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import net.scalan.jpa.PersistenceService;
import net.scalan.jpa.model.DBELink;
import net.scalan.jpa.model.DBELinkCanValue;
import net.scalan.jpa.model.DBELinkCanValueHistory;

/**
 *
 * @author scalan
 */
class ELinkScaner extends Thread {

    public final int ST_PAUSE = 1;

    public final int ST_START = 2;

    public final int ST_WORK = 3;

    public final int ST_STOP = 4;

    public static final long TIMEOUT = 500;

    private DBELink elink;

    private long dt;

    private int status = ST_PAUSE;

    public ELinkScaner(DBELink elink) {
        this.elink = elink;
        if (elink != null && elink.getHost() != null && elink.getPort() != null) {
            this.setName(elink.getName());
        }
        System.out.println(">>> Init '" + elink.getName() + "'...");
    }

    private InputStream is = null;

    @Override
    public void run() {
        if (elink != null) {
            System.out.println(">>> Run '" + elink.getName() + "'...");
            InputStream stream = null;
            String canPackage = null;
            while (getStatus() != ST_STOP) {
                if (getStatus() != ST_PAUSE) {
                    if (getStatus() == ST_START) {
                        try {
                            System.out.println(">>> Try to open port '" + elink.getName() + "' Host: '" + elink.getHost() + "' Port: " + elink.getPort() + "...");
                            Socket serverSocket = new Socket("192.168.1.3"/*elink.getHost()*/, 10004/*elink.getPort()*/);
                            stream = serverSocket.getInputStream();
                            dt = System.currentTimeMillis();
                            setStatus(ST_WORK);
                        } catch (IOException ex) {
                            setStatus(ST_PAUSE);
                            System.err.println("Error: " + ex);
                        }
                    }
                    if (getStatus() == ST_WORK) {
                        System.out.println(">>> Wait for data '" + elink.getName() + "'...");
                        if (stream != null) {
                            try {
                                // Read can package from the socket
                                canPackage = "";
                                int c = 0;
                                while (getStatus() == ST_WORK && c != 13) {
                                    if (is != null && is.available() > 0) {
                                        c = is.read();
                                        if (c != 13) {
                                            canPackage += (char) c;
                                        }
                                    } else {
                                        try {
                                            Thread.sleep(10);
                                        } catch (InterruptedException ex) {
                                        }
                                    }
                                }
                                //canPackage = "e1234567880102030405060708";
                                if (canPackage != null && canPackage.length() > 0 && canPackage.charAt(0) == 'e') {
                                    dt = System.currentTimeMillis();
                                    doProcessCanPackage(canPackage);
                                    System.out.println(canPackage);
                                } else {
                                    try {
                                        Thread.sleep(50);
                                    } catch (InterruptedException ex) {
                                    }
                                }
                            } catch (IOException ex) {
                                setStatus(ST_PAUSE);
                                System.err.println("Error: " + ex);
                            }
                        } else {
                            setStatus(ST_START);
                        }
                    }
                }
                try {
                    Thread.sleep(50);
                } catch (InterruptedException ex) {
                }
            }
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException ex) {
                    System.err.println("Error: " + ex);
                }
            }
        }
    }

    /**
     * @return the dt
     */
    public long getDt() {
        return dt;
    }

    private void doProcessCanPackage(String canPackage) {
        if (canPackage != null && canPackage.length() > 10) {
            String strCan_id = canPackage.substring(1, 9);
            try {
                long can_id = Long.parseLong(strCan_id);
                String strDataLength = canPackage.substring(9, 10);
                int data[] = null;
                int dataLength = Integer.parseInt(strDataLength);
                if (dataLength > 0) {
                    data = new int[dataLength];
                    for (int i = 0; i < dataLength; i++) {
                        String strValue = canPackage.substring(10 + (i * 2), 11 + (i * 2));
                        int value = Integer.parseInt(strValue);
                        data[i] = value;
                    }
                }
                storeCanData(canPackage, can_id, data);
            } catch (NumberFormatException ex) {
                System.err.println(ex);
                ex.printStackTrace();
            }
        }
    }

    private void storeCanData(String canPackage, long can_id, int[] data) {
        if (1 == 1) {
            storeCanValue(canPackage, can_id, data);
        } else {
            storeOtherCanValue(canPackage, can_id, data);
        }
    }

    private synchronized void storeCanValue(String canPackage, long can_id, int[] data) {
        EntityManager em = PersistenceService.getEntityManager();
        if (em != null) {
            try {
                em.getTransaction().begin();
                Query q = em.createQuery(
                        "SELECT d "
                        + "FROM DBELinkCanValue AS d "
                        + "WHERE d.can_id=:can_id");
                q.setParameter("can_id", can_id);
                DBELinkCanValue record = null;
                if (q.getResultList() != null && q.getResultList().size() > 0) {
                    record = (DBELinkCanValue) q.getResultList().get(0);
                }
                if (record == null) {
                    record = new DBELinkCanValue();
                    record.setCan_id(can_id);
                    record.setDataString(canPackage);
                    em.persist(record);
                } else {
                    record.setDataString(canPackage);
                    em.merge(record);
                }

                DBELinkCanValueHistory historyRecord = new DBELinkCanValueHistory();
                historyRecord.setElinkCanValue(record);
                historyRecord.setDt(System.currentTimeMillis());
                historyRecord.setDataString(canPackage);
                em.persist(historyRecord);
                em.getTransaction().commit();
            } catch (Exception ex) {
                System.err.println(ex);
                ex.printStackTrace();
                em.getTransaction().rollback();
            }
        }
    }

    private synchronized void storeOtherCanValue(String canPackage, long can_id, int[] data) {
    }

    /**
     * @return the status
     */
    public int getStatus() {
        return status;
    }

    /**
     * @param status the status to set
     */
    public void setStatus(int status) {
        this.status = status;
    }
}
